package ar.edu.utn.frsf.proyectofinal.sistemadecontrolmodbus.devicecontroller.test;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

import net.wimpi.modbus.ModbusIOException;
import net.wimpi.modbus.io.ModbusTransport;
import net.wimpi.modbus.msg.ModbusMessage;
import net.wimpi.modbus.msg.ModbusRequest;
import net.wimpi.modbus.msg.ModbusResponse;

public class MocketPoolingModbusTransport implements ModbusTransport {

	private int transaction = 0;
	private ModbusRequest[] requests;
	private ModbusResponse[] responses;
	private CyclicBarrier barrier;
	
	@Override
	public void close() throws IOException {	
	}

	@Override
	public ModbusRequest readRequest() throws ModbusIOException {
		throw new ModbusIOException();
	}

	@Override
	public ModbusResponse readResponse() throws ModbusIOException {
		ModbusResponse res = getResponses()[getTransaction() % getResponses().length];
		res.setTransactionID(getTransaction());
		setTransaction(getTransaction() + 1);
		return res;
	}

	@Override
	public void writeMessage(ModbusMessage msg) throws ModbusIOException {
		try {
			// Verify request type is the expected type 
			assertTrue(msg.getClass().isInstance(getRequests()[getTransaction() % getRequests().length]));
			assertEquals(msg.getTransactionID() , getTransaction());
			barrier.await();
			
		} catch (InterruptedException e) {
			throw new ModbusIOException();
		} catch (BrokenBarrierException e) {
			throw new ModbusIOException();
		}
		
	}

	/**
	 * @return the transaction
	 */
	public int getTransaction() {
		return transaction;
	}

	/**
	 * @param transaction the transaction to set
	 */
	public void setTransaction(int transaction) {
		this.transaction = transaction;
	}

	/**
	 * @return the requests
	 */
	public ModbusRequest[] getRequests() {
		return requests;
	}

	/**
	 * @param modbusRequests the requests to set
	 */
	public void setRequests(ModbusRequest[] modbusRequests) {
		this.requests = modbusRequests;
	}

	/**
	 * @return the responses
	 */
	public ModbusResponse[] getResponses() {
		return responses;
	}

	/**
	 * @param responses the responses to set
	 */
	public void setResponses(ModbusResponse[] responses) {
		this.responses = responses;
	}

	/**
	 * @return the barrier
	 */
	public CyclicBarrier getBarrier() {
		return barrier;
	}

	/**
	 * @param barrier the barrier to set
	 */
	public void setBarrier(CyclicBarrier barrier) {
		this.barrier = barrier;
	}

}
